package org.hoefling.bean.auction;

import de.dailab.jiactng.agentcore.comm.ICommunicationAddress;
import de.dailab.jiactng.agentcore.comm.message.JiacMessage;
import java.util.concurrent.atomic.AtomicInteger;
import org.hoefling.ontology.AuctionProtocol;
import org.hoefling.ontology.BiddingStrategy;
import org.hoefling.ontology.Message;
import org.hoefling.ontology.MoneyInfo;

/**
 *
 * @author Kseniya
 */
public class Participant extends AuctionMember {

    public static final int ITEMS_TO_GAIN = 3;
    public static final int INITIAL_ASSETS = 500;
    private BiddingStrategy strategy;
    private AtomicInteger price = new AtomicInteger(0);
    private int itemsGot = 0;
    private int assets = INITIAL_ASSETS;
    private boolean leading = false;

    @Override
    public void consume(JiacMessage msg) {
        Message payload = (Message) msg.getPayload();
        AuctionProtocol type = (AuctionProtocol) payload.getType();
        switch (type) {
            case OPENING:
                sendMsgPersonal(new MoneyInfo(AuctionProtocol.REGISTER, assets), msg.getSender());
                break;
            case STARTED:
                MoneyInfo info = (MoneyInfo) payload;
                price.set(info.getSum());
                break;
            case ENDED:
                leading = false;
                break;
            case CLOSED:
                log.error("Agent " + thisAgent.getAgentName()
                        + " got " + itemsGot + " items, spent "
                        + (INITIAL_ASSETS - assets) + " AE.");
                break;
            case CALL_FOR_PROPOSALS:
                info = (MoneyInfo) payload;
                if (leading) {
                    leading = price.get() >= info.getSum();
                }
                if (!leading) {
                    propose(info.getSum(), msg.getSender());
                }
                break;
            case REQUEST_WINNER:
                info = (MoneyInfo) payload;
                itemsGot++;
                assets -= info.getSum();
                break;
            case ACCEPT_PROPOSAL:
                info = (MoneyInfo) payload;
                price.set(info.getSum());
                leading = true;
                break;
            case REJECT_PROPOSAL:
                info = (MoneyInfo) payload;
                price.set(info.getSum());
                leading = false;
//                log.error("my price was rejected! (curr price " + info.getSum() + ") offering new price...");
                propose(price.get(), msg.getSender());
                break;
            default:
                break;
        }
    }

    private void propose(int currPrice, ICommunicationAddress initiator) {
        if (itemsGot >= 3) {
            return;
        }
        int offer = strategy.offer(currPrice, assets, ITEMS_TO_GAIN - itemsGot);
        if (offer > currPrice && assets - offer > 0) {
//            log.error("Proposing price " + offer);
            sendMsgPersonal(new MoneyInfo(AuctionProtocol.PROPOSE, offer), initiator);
        }
    }

    public BiddingStrategy getStrategy() {
        return strategy;
    }

    public void setStrategy(BiddingStrategy strategy) {
        this.strategy = strategy;
    }
}
